# encoding: UTF-8

"""
这里的Demo是一个最简单的策略实现，并未考虑太多实盘中的交易细节，如：
1. 委托价格超出涨跌停价导致的委托失败
2. 委托未成交，需要撤单后重新委托
3. 断网后恢复交易状态
4. 等等
这些点是作者选择特意忽略不去实现，因此想实盘的朋友请自己多多研究CTA交易的一些细节，
做到了然于胸后再去交易，对自己的money和时间负责。
也希望社区能做出一个解决了以上潜在风险的Demo出来。
"""


from base.ctaBase import *
from strategy.ctaTemplate import CtaTemplate

########################################################################
class MoveAverageStrategy(CtaTemplate):
    """移动均线策略"""
    className = 'DualThrust'
    author = u'何雨'

    # 策略变量
    bar = None
    barMinute = EMPTY_STRING

    initDays = 0
    hisBarOpen = []
    hisBarClose = []
    hisBarHigh = []
    hisBarLow = []

    NPeriod = 7

    pos = 0

    upLimitRatio = 0.7
    downLimitRatio = 0.7

    limitProfit = 10
    limitLost = 10

    currTime = ""
    currHour= ""
    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(MoveAverageStrategy, self).__init__(ctaEngine, setting)
        
    #----------------------------------------------------------------------
    def onInit(self):
        """初始化策略（必须由用户继承实现）"""
        self.writeCtaLog(u'MoveAverage策略初始化')
        if self.ctaEngine.mode == self.ctaEngine.BAR_MODE: 
            initData = self.loadBar(self.initDays)
            
            for bar in initData:
                self.onBar(bar)
        else:
            initData = self.loadTick(self.initDays)
            for tick in initData:
                self.onTick(tick)
        
        self.putEvent()
        
    #----------------------------------------------------------------------
    def onStart(self):
        """启动策略（必须由用户继承实现）"""
        self.writeCtaLog(u'移动均线策略启动')
        self.putEvent()
    
    #----------------------------------------------------------------------
    def onStop(self):
        """停止策略（必须由用户继承实现）"""
        self.writeCtaLog(u'移动均线策略停止')
        self.putEvent()
        
    #----------------------------------------------------------------------
    def onBar(self, bar):
        """收到Bar推送（必须由用户继承实现）"""

        #记录历史数据
        self.hisBarClose.append(bar.close)
        self.hisBarHigh.append(bar.high)
        self.hisBarOpen.append(bar.open)
        self.hisBarLow.append(bar.low)
        #print bar

        self.currTime = bar.datetime.strftime("%H%M%S")
        self.currDate = bar.datetime.strftime("%Y%m%d")

        if (len(self.hisBarClose) < 60):
            return

        MA30 = sum(self.hisBarClose[-30:]) / 30
        MA35 = sum(self.hisBarClose[-35:]) / 35
        MA40 = sum(self.hisBarClose[-40:]) / 40
        MA45 = sum(self.hisBarClose[-45:]) / 45
        MA60 = sum(self.hisBarClose[-60:]) / 60

        #收盘前平仓
        if (self.currTime >="145500") and (self.currTime <= "145800") \
            and (not self.ctaEngine.isPositionNextDate) and (self.ctaEngine.getTotalPosition() != 0)\
                and self.ctaEngine.isFinishedOrders():
            if self.ctaEngine.getLongPosition() != 0:
                self.sell(bar.open, 1)
            elif self.ctaEngine.getShortPosition() != 0:
                self.cover(bar.open, 1)
            return

        #离场
        if False:
            if self.ctaEngine.isFinishedOrders() and self.ctaEngine.getTotalPosition() >0:
                #止损平多
                if self.ctaEngine.getLongPosition() >0:
                    if bar.close < MA60:
                        self.sell(bar.close, 1)
                        return
                #止损平空
                if self.ctaEngine.getShortPosition() >0:
                    if bar.close > MA60:
                        self.cover(bar.close, 1)
                        return
        if self.ctaEngine.isLimitLose:
            if self.ctaEngine.isFinishedOrders() and self.ctaEngine.getTotalPosition() >0:
                #止损平多
                if self.ctaEngine.getLongPosition() >0:
                    if (bar.open + self.limitLost) < self.ctaEngine.getLongCostPrice():
                        self.sell(bar.close, 1)
                        return
                #止损平空
                if self.ctaEngine.getShortPosition() >0:
                    if (bar.open + self.limitLost) > self.ctaEngine.getShortCostPrice():
                        self.cover(bar.close, 1)
                        return


        #MA
        #print self.hisBarClose

        #条件
        buyCross = (MA30 > MA60) and (MA35 > MA60) and (MA40 > MA60) and (MA45 > MA60)
        sellCross = (MA30 < MA60) and (MA35 < MA60) and (MA40 < MA60) and (MA45 < MA60)
        lastPrice = bar.close

        #print rangeBar, upLimitPrice, downLimitPrice, lastPrice

        if buyCross:
            #print "Up"
            sign = {'time': bar.datetime.strftime("%H%M%S"), 
                    'MA30': MA30,
                    'MA40': MA40,
                    'MA45': MA45,
                    'MA60': MA60}
            #self.saveSignal(self.currDate, sign)
            if self.ctaEngine.isFinishedOrders() and self.ctaEngine.getLongPosition() == 0 and self.ctaEngine.getTotalPosition() == 0:
                self.buy(bar.high, 1)
            elif self.ctaEngine.isFinishedOrders() and self.ctaEngine.getLongPosition() == 0 and self.ctaEngine.getTotalPosition() != 0:
                self.cover(bar.close, 1)
                self.buy(bar.close, 1)

        if sellCross:
            sign = {'time': bar.datetime.strftime("%H%M%S"), 
                    'MA30': MA30,
                    'MA40': MA40,
                    'MA45': MA45,
                    'MA60': MA60}
            #self.saveSignal(self.currDate, sign)
            if self.ctaEngine.isFinishedOrders() and self.ctaEngine.getShortPosition() == 0 and self.ctaEngine.getTotalPosition() == 0:
                self.short(bar.low, 1)

            elif self.ctaEngine.isFinishedOrders() and self.ctaEngine.getShortPosition() == 0 and self.ctaEngine.getTotalPosition() != 0:
                self.sell(bar.low, 1)
                self.short(bar.low, 1)
                #print "Cross Sell"
                
        # 发出状态更新事件
        self.putEvent()
        
    #----------------------------------------------------------------------
    def onOrder(self, order):
        """收到委托变化推送（必须由用户继承实现）"""
        # 对于无需做细粒度委托控制的策略，可以忽略onOrder
        pass
    
    #----------------------------------------------------------------------
    def onTrade(self, trade):
        """收到成交推送（必须由用户继承实现）"""
        # 对于无需做细粒度委托控制的策略，可以忽略onOrder
        pass
    
